package cn.tedu.justone.pack01;

import java.util.concurrent.locks.StampedLock;

/**
 * ZZ：JustOne
 * VX：Andylau2020smile
 * DY：JustOne2018
 * ZT：《》
 */
public class Demo12_乐观读写锁StampedLock的读写转换 {

    //乐观读写锁StampedLock的读写转换
    //乐观读写锁StampedLock的读写转换
    //乐观读写锁StampedLock的读写转换
    //
    // 先把上一篇《乐观读写锁StampedLock》的代码复制过来，
    // 删除其中【写】的部份。按照下面的代码，尝试把读锁转换成写锁。
    // 多运行几次，总会看到转换成功的。

    static StampedLock stampedLock = new StampedLock();
    static int num = 1;

    public static void main(String[] args) {

        for (int i = 0; i < 3; i++) {
            new Thread("线程" + i){
                @Override
                public void run() {
                    readData();
                }
            }.start();
        }
    }

    //读数据后，转成写锁
    public static void readData(){
        //悲观读锁
        long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName() + "正在读数据: num = " + num);
        try{
            //尝试转换为写锁
            System.out.println(Thread.currentThread().getName() + "正在尝试转换为写锁");
            long ws = stampedLock.tryConvertToWriteLock(stamp);
            //转换成功
            if(ws != 0L){
                stamp = ws; //更新戳印
                System.out.println(Thread.currentThread().getName() + "转换写锁成功，戳印是" + stamp);
                num++;
                System.out.println(Thread.currentThread().getName() + "正在写数据: num = " + num);
            }else{
                System.out.println(Thread.currentThread().getName() + "转换写锁失败，释放悲观读锁");
                stampedLock.unlockRead(stamp);//-----读转写 转换失败，释放读
                stamp = stampedLock.writeLock();//---强制获取悲观写锁，否则释放时会报错
            }
        }finally {
            stampedLock.unlock(stamp);//释放锁
        }

    }

}
